import { useCallback, useState, useEffect, useMemo, memo } from 'react'
import propsType from 'prop-types'
import { Table, TableBody, TableContainer, TableHead, TableRow, Paper, Checkbox, IconButton, Box, TableCell, Collapse } from '@mui/material'
import StyledTableRow from '@/components/MyTable/StyledTableRow'
import StyledTableCell from './StyledTableCell'
import StyledTableSortLabel from './StyledTableSortLabel'
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import { EmptyState } from '@brightlayer-ui/react-components';
import DevicesIcon from '@mui/icons-material/Devices';
import GlobalLoading from '../GlobalLoading/GlobalLoading'
import './MyTable.scss'

const CustomTableBodyRow = (props) => {
  const { row, clickSeletedNode, rowKey, selectedNode, showCollapse, showChecked, getRowIndaterminate, onSeletedRow, tablePorps, beforeCollapse, index } = props
  const [open, setOpen] = useState(false)

  const collapseColspan = useMemo(() => (
    tablePorps.length + 1 + (showChecked ? 1 : 0)
  ), [tablePorps, showChecked])

  const collapseClick = useCallback(() => {
    // 如果当前是要展开表格并且展开表格前需要进行一些处理，则执行函数
    if (!open && beforeCollapse && typeof (beforeCollapse) === 'function') {
      beforeCollapse(row)
    }
    setOpen(!open)
  }, [open, beforeCollapse])
  return (
    <>
      <StyledTableRow hover selected={clickSeletedNode && clickSeletedNode[rowKey] === row[rowKey]} onClick={() => selectedNode(row)} className={`${index % 2 ? 'customRowClass' : ''}`}>
        {
          showCollapse && (
            <StyledTableCell style={{ width: '70px' }}>
              <IconButton
                style={{ borderRadius: '50%' }}
                size="small"
                onClick={(event) => collapseClick(event)}
              >
                {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
              </IconButton>
            </StyledTableCell>
          )
        }
        {
          showChecked && (
            <StyledTableCell style={{ width: '70px' }}>
              <Checkbox
                color="primary"
                checked={getRowIndaterminate(row[rowKey])}
                onChange={() => onSeletedRow(row)}
              />
            </StyledTableCell>
          )
        }
        {
          tablePorps.map((prop, index) => (
            <StyledTableCell key={index}>
              {
                prop.valueFormat && typeof (prop.valueFormat) === 'function' ? prop.valueFormat(row[prop.read]) : row[prop.read]
              }
            </StyledTableCell>
          ))
        }
      </StyledTableRow>
      {
        showCollapse && (
          <StyledTableRow>
            <TableCell colSpan={collapseColspan} style={{ padding: 0 }}>
              <Collapse in={open} timeout="auto" unmountOnExit>
                <Box style={{ padding: '0.8rem' }}>
                  { row.collapseChildren ? row.collapseChildren : undefined }
                </Box>
              </Collapse>
            </TableCell>
          </StyledTableRow>
        )
      }
    </>
  )
}

/**
 * 封装表格组件props
 * @param {array} tableTitle 表格标题头{ id, title, width, sort } 列的id（一般是列的属性值), 列的标题，列的宽度, 列是否需要排序
 * @param {array} tablePorps 表格每一列读取的属性{read, valueFormat} 列读取的属性，值格式化的函数
 * @param {array} tableData 表格数据
 * @param {string} rowKey 每一行数据的唯一标识符，必须有
 * @param {boolean} showChecked 是否展示复选框
 * @param {function} getCheckedRows 在展示复选框的情况下，如果复选框的数据有所变化就抛出去
 * @param {function} getTableSortObj 获取当前排序的属性
 * @param {function} seletedNodeChange 鼠标点击节点变化时要抛出去
 * @param {boolean} showCollapse 每一行是否能够展开
 * @param {function} beforeCollapse 每一个节点展开前触发的方法，例如在展开前要先给渲染的节点
 * @param {boolean} isLoading 是否处于加载状态
 * @param {string} textAlign 文字方向，left、center、right
 * @returns 
 */
const MyTable = (props) => {
  const { tableTitle, tablePorps, tableData, rowKey, showChecked, getCheckedRows, getTableSortObj, seletedNodeChange, showCollapse, beforeCollapse, isLoading, textAlign } = props
  const [checkedArr, setCheckedArr] = useState([])
  const [orderBy, setOrderBy] = useState('');
  const [order, setOrder] = useState('asc');
  const [clickSeletedNode, setClickSelectedNode] = useState(null)

  const onSelectAllClick = useCallback(() => {
    if (checkedArr && checkedArr.length > 0 && (checkedArr.length === tableData.length)) { // 如果已经勾选全部，则清空
      setCheckedArr([])
    } else if (checkedArr && checkedArr.length > 0 && (checkedArr.length < tableData.length)) { // 如果已经半勾选状态，则选择全部
      setCheckedArr(tableData.slice(0))
    } else { // 如果还没有勾选，则全部勾选上
      setCheckedArr(tableData.slice(0))
    }
  }, [tableData, checkedArr])

  // 表格数据变化的时候要记得把复选框勾选项清空
  useEffect(() => {
    setCheckedArr([])
  }, [tableData])

  // 勾选框的情况下，如果勾选框变化了就要抛出去
  useEffect(() => {
    if (getCheckedRows && typeof (getCheckedRows) === 'function') {
      getCheckedRows(checkedArr)
    }
  }, [checkedArr, getCheckedRows])

  // 判断某一行是否被勾选上
  const getRowIndaterminate = useCallback((key) => {
    const index = checkedArr.findIndex(item => {
      return item[rowKey] === key
    })
    if (index >= 0) { // 如果该行已经被勾选上了，则返回TRUE
      return true
    }
    return false
  }, [checkedArr])

  const onSeletedRow = useCallback((row) => {
    const index = checkedArr.findIndex(item => {
      return item[rowKey] === row[rowKey]
    })
    if (index >= 0) { // 如果该行已经被勾选上了，则从数组里删除
      if (index === 0) { // 如果是第一个数组
        setCheckedArr(checkedArr.slice(1))
      } else if (index === checkedArr.length) {
        setCheckedArr(checkedArr.slice(0, index))
      } else {
        setCheckedArr([...checkedArr.slice(0, index), ...checkedArr.slice(index + 1)])
      }
    } else {
      setCheckedArr([...checkedArr, row])
    }
  }, [checkedArr])

  const createSortHandler = useCallback((property) => {
    if (orderBy !== property) {
      setOrderBy(property)
    }
    setOrder(order === 'asc' ? 'desc' : 'asc')
  }, [orderBy, order])

  // 排序变化的时候要抛出去
  useEffect(() => {
    if (getTableSortObj && typeof (getTableSortObj) === 'function') {
      const tableSortObj = {
        direction: orderBy,
        order
      }
      getTableSortObj(tableSortObj)
    }
  }, [getTableSortObj, orderBy, order])

  const selectedNode = useCallback((row) => {
   if (clickSeletedNode && clickSeletedNode[rowKey] === row[rowKey]) {
    setClickSelectedNode(null)
   } else {
    setClickSelectedNode(row)
   }
  }, [clickSeletedNode])

  // 当前点击的节点要抛出去
  useEffect(() => {
    if (seletedNodeChange && typeof (seletedNodeChange) === 'function') {
      seletedNodeChange(clickSeletedNode)
    }
  }, [seletedNodeChange, clickSeletedNode])

  return (
    <div className="myTableClass">
      {
        isLoading ? <GlobalLoading /> :
        tableData?.length ?
        (
          <TableContainer component={Paper} style={{height: '100%', '--textAlign': textAlign}}>
            <Table sx={{ minWidth: 650 }} stickyHeader>
              <TableHead>
                <TableRow>
                  {
                    showCollapse && (
                      <StyledTableCell style={{ width: '70px' }} />
                    )
                  }
                  {
                    showChecked && (
                      <StyledTableCell style={{ width: '70px' }}>
                        <Checkbox
                          color="primary"
                          indeterminate={checkedArr && checkedArr.length > 0 && (checkedArr.length < tableData.length)}
                          checked={checkedArr && checkedArr.length > 0 && (checkedArr.length === tableData.length)}
                          onChange={onSelectAllClick}
                        />
                      </StyledTableCell>
                    )
                  }
                  {tableTitle.map((item, index) => {
                    return (
                      item.sort ?
                      <StyledTableCell key={index} style={{ width: item.width ? item.width : '' }}>
                        <StyledTableSortLabel
                          active={orderBy === item.id}
                          direction={orderBy === item.id ? order : 'asc'}
                          onClick={() => createSortHandler(item.id)}
                        >
                          {item.title}
                        </StyledTableSortLabel>
                      </StyledTableCell>:
                      <StyledTableCell key={index} style={{ width: item.width ? item.width : '' }}>{item.title}</StyledTableCell>
                    )
                  })}
                </TableRow>
              </TableHead>
              <TableBody>
                {
                  tableData.map((row, index) => (
                    <CustomTableBodyRow
                      key={row[rowKey]}
                      index={index}
                      row={row}
                      clickSeletedNode={clickSeletedNode}
                      rowKey={rowKey}
                      selectedNode={selectedNode}
                      showCollapse={showCollapse}
                      showChecked={showChecked}
                      getRowIndaterminate={getRowIndaterminate}
                      onSeletedRow={onSeletedRow}
                      tablePorps={tablePorps}
                      beforeCollapse={beforeCollapse}
                    >
                    </CustomTableBodyRow>
                  ))
                }
              </TableBody>
            </Table>
          </TableContainer>
        ) :
        (
          <EmptyState
            icon={<DevicesIcon fontSize={'inherit'} />}
            title={'NO DATA'}
          />
        )
      }
    </div>
  )
}

MyTable.propTypes = {
  tableData: propsType.array.isRequired,
  tablePorps: propsType.array.isRequired,
  tableTitle: propsType.array.isRequired,
  rowKey: propsType.string.isRequired,
  showChecked: propsType.bool,
  getCheckedRows: propsType.func,
  getTableSortObj: propsType.func,
  seletedNodeChange: propsType.func,
  showCollapse: propsType.bool,
  beforeCollapse: propsType.func,
  isLoading: propsType.bool,
  textAlign: propsType.string
}

MyTable.defaultProps = {
  showCollapse: false,
  textAlign: 'left'
}

export default memo(MyTable)